#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdarg.h>
#include "public.h"
char g_resetFlag =0;
char udpRecBuf[1024] = {0};
char udpSentBuf[102400] = {0};
// SERVER_COM_TYPE
#define DEBUG_STRING_MAX_LEN 1024
typedef struct
{
	unsigned int ModuleId;
	unsigned int length;
	unsigned char data[DEBUG_STRING_MAX_LEN];
} S_DebugMsg;

enum
{
	noDebug = 0,
	serialDebug,
	udpDebug,
	mqttDebug
} debugWhere;

 char g_debugWhere = noDebug;
//char g_debugWhere=mqttDebug;
static struct sockaddr_in g_localAddr;
static struct sockaddr_in g_remoteAddr;
static struct sockaddr_in g_debugAddr;
static int g_sockfd;
void DebugPrint(char *fmt, ...);

void *udpServerThread(void)
{
	g_resetFlag=0;
	g_sockfd = socket(AF_INET, SOCK_DGRAM, 0);

	//创建网络通信对象
	//	    struct sockaddr_in addr;
	g_localAddr.sin_family = AF_INET;
	g_localAddr.sin_port = htons(5211);
	//addr.sin_addr.s_addr=inet_addr("127.0.0.1");
	g_localAddr.sin_addr.s_addr = INADDR_ANY;
	//INADDR_ANY

	//绑定socket对象与通信链接
	int ret = -1;
	while (ret == -1)
	{
		ret = bind(g_sockfd, (struct sockaddr *)&g_localAddr, sizeof(g_localAddr));
		if (0 > ret)
		{
			DebugPrint("bind erro\n");
			sleep(3);
		}
	}
	DebugPrint("bind ok\n");
	socklen_t len = sizeof(g_remoteAddr);

	while (1)
	{
		DebugPrint("udp waiting for recv\n");
		int recvLen = recvfrom(g_sockfd, &udpRecBuf, sizeof(udpRecBuf), 0, (struct sockaddr *)&g_remoteAddr, &len);
		if (recvLen > 0)
		{
			if (!strcmp(udpRecBuf, "debug"))
			{
				g_debugWhere = udpDebug;
				g_debugAddr = g_remoteAddr;
			}
			else
			{
				int len = comPackePasra(&udpRecBuf, &udpSentBuf, recvLen);
				if(len!=0)sendto(g_sockfd, &udpSentBuf, len, 0, (struct sockaddr *)&g_remoteAddr, sizeof(g_remoteAddr));
				if(g_resetFlag == 1)
				{
					sleep(1);
					exit(EXIT_SUCCESS);
				}
			}
		}
	}
	close(g_sockfd);
}
int comPackePasra(char *recvBuf, char *sendBuf, int recPacketLen)
{
	SERVER_COM_HEAD_TYPE *pCom;
	int i;
	int len;
	char *ptr;
	DebugPrint("\n udp recieve packet:");

	for (i = 0; i < recPacketLen; i++)
	{
		sendBuf[i] = recvBuf[i];
		DebugPrint(" %x", sendBuf[i]);
	}
	DebugPrint("\nrecPacketLen=%d\n", recPacketLen);

	pCom = (SERVER_COM_HEAD_TYPE *)sendBuf;

	int crc = modbusCrc16(&sendBuf[3], recPacketLen - 6);
	int temp = sendBuf[recPacketLen - 2] * 0x100 + sendBuf[recPacketLen - 3];
	if (crc != temp)
	{
		DebugPrint("udp crc rev err calcrc=%x recvtemp=%x\n", crc, temp);
		return;
	}
	if (pCom->packetCmd == mCmd_setData)
	{
		len =set_jxDevDataValue(&sendBuf[SERVER_COM_PACKET_HEAD_LEN],recPacketLen-SERVER_COM_PACKET_HEAD_LEN-3);
	}
	else if (pCom->packetCmd == mCmd_getSqilte)
	{
		recvBuf[recPacketLen - 3] = 0;
		len = sql_general_interface(&recvBuf[SERVER_COM_PACKET_HEAD_LEN], &sendBuf[SERVER_COM_PACKET_HEAD_LEN]);
	}
	else if (pCom->packetCmd == mCmd_setSqilte)
	{
		recvBuf[recPacketLen - 3] = 0;
		// len = sql_general_set_interface(&recvBuf[SERVER_COM_PACKET_HEAD_LEN], &sendBuf[SERVER_COM_PACKET_HEAD_LEN]);
		len = sql_general_set_interface(&recvBuf[SERVER_COM_PACKET_HEAD_LEN]);
	}
	else if (pCom->packetCmd == mCmd_getDevRealData)
	{
		len = get_jxDevAllRealData(&sendBuf[SERVER_COM_PACKET_HEAD_LEN]);
	}
	else if (pCom->packetCmd == mCmd_devReset)
	{
		g_resetFlag = 1;
		len = 0;
	}
	else if (pCom->packetCmd == mCmd_kaizhanReport)
	{
		base64_encode((unsigned char *)recvBuf,(char *)sendBuf,recPacketLen);
		// DebugPrint("\n base64 packet:");
		// for (i = 0; i < strlen(sendBuf); i++)
		// {
		// 	DebugPrint(" %x", sendBuf[i]);
		// }
		// DebugPrint("\nbase64PacketLen=%d\n", strlen(sendBuf));
		AP_circleBuff_WritePacket((INT8U *)sendBuf, strlen(sendBuf), DTU2MQTPA);
		len = 0;
	}
	// else if (pCom->packetCmd == mCmd_pollAllRealDevData)
	// {
	// 	len = get_jxDevAllRealData(&sendBuf[SERVER_COM_PACKET_HEAD_LEN]);
	// }

	else{
		return 0;
	}
	pCom->packetAnswer = 0x00;
	if (len == 0 && pCom->packetCmd != mCmd_devReset && pCom->packetCmd != mCmd_kaizhanReport)
	{
		pCom->packetAnswer = 0x01;
	}
	len += SERVER_COM_PACKET_HEAD_LEN;
	pCom->packetLen = (len - 3);
	crc = modbusCrc16(&sendBuf[3], len - 3);
	
	sendBuf[len] = crc;
	sendBuf[len + 1] = crc >> 8;
	sendBuf[len + 2] = 0x7e;
	// DebugPrint("\n udp ack packet: ");
	// for (i = 0; i < len + 3; i++)
	// {
	// 	DebugPrint("%x ", sendBuf[i]);
	// }
	// DebugPrint("\n");

	// printf("\n udp ack packet: ");
	// for (i = 0; i < len + 3; i++)
	// {
	// 	printf("%x ", sendBuf[i]);
	// }

	return len + 3;
}

void DebugPrint(char *fmt, ...)
{
	S_DebugMsg debugMsg;
	int printStrLen = 0;

	if (noDebug == g_debugWhere)
		return;
	va_list ap;
	va_start(ap, fmt);
	printStrLen = vsnprintf((char *)&debugMsg.data[0], DEBUG_STRING_MAX_LEN, fmt, ap);
	va_end(ap);

	if (g_debugWhere == serialDebug)
	{
		printf("%s", debugMsg.data);
		return;
	}
	if (g_debugWhere == udpDebug)
	{
		debugMsg.length = htons(printStrLen);
		sendto(g_sockfd, &debugMsg.data, printStrLen, 0, (struct sockaddr *)&g_debugAddr, sizeof(struct sockaddr_in));
	}
	if (g_debugWhere == mqttDebug)
	{
		debugMsg.length = htons(printStrLen);

		pthread_mutex_lock(&comBuff0.lock);
		if (printStrLen > 2)
		{
			AP_circleBuff_WritePacket((INT8U *)debugMsg.data, printStrLen, DTU2MQTPC);
		}
		pthread_mutex_unlock(&comBuff0.lock);
		//sendto(g_sockfd, &debugMsg.data, printStrLen, 0,(struct sockaddr *)&g_debugAddr, sizeof(struct sockaddr_in));
	}
}
